package com.lwq.imserver.controller;

import cn.hutool.core.io.FileTypeUtil;
import com.lwq.imserver.config.CoreConfig;
import com.lwq.imserver.config.ServerConfig;
import com.lwq.imserver.constants.Constants;
import com.lwq.imserver.model.ChatMessage;
import com.lwq.imserver.model.File;
import com.lwq.imserver.model.Result;
import com.lwq.imserver.model.system.SysUser;
import com.lwq.imserver.util.Base64Util;
import com.lwq.imserver.util.MongoUtil;
import com.lwq.imserver.util.SpringContextUtil;
import com.lwq.imserver.util.StringUtils;
import com.lwq.imserver.util.file.FileUploadUtils;
import com.lwq.imserver.util.file.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.http.MediaType;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2022/1/26 9:28
 */
@RestController
@Slf4j
@CrossOrigin("*")
public class CommonController {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private PasswordEncoder pe;
    @Autowired
    private ServerConfig serverConfig;
    @Autowired
    private MongoUtil<ChatMessage> messageMongoUtil;

    @PostMapping("handleAccount")
    public void handleAccount(@RequestBody SysUser user) {
        String pass = Base64Util.encode(user.getPassword());
        user.setPassword(pe.encode(pass));
        user.setCreateDate(new Date());
        mongoTemplate.insert(user);
    }

    @GetMapping("handleAvatar")
    @Transactional(rollbackFor = Exception.class)
    public void handleAvatar() {
        List<ChatMessage> list = mongoTemplate.findAll(ChatMessage.class);
        for (ChatMessage message : list) {
            if (StringUtils.isNotEmpty(message.getFromAvatar())) {
                String avatar = message.getFromAvatar();
                message.setFromAvatar(avatar.replaceAll("http", "https").replaceAll("9006", "9009"));
                messageMongoUtil.update(message, message.getId());
            }
        }
    }

    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete   是否删除
     */
    @GetMapping("common/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        try {
            if (!FileUtils.checkAllowDownload(fileName)) {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = CoreConfig.getDownloadPath() + fileName;

            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete) {
                FileUtils.deleteFile(filePath);
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }


    /**
     * 通用上传请求
     */
    @PostMapping("/common/upload")
    @CrossOrigin("*")
    public Result uploadFile(MultipartFile file) throws Exception {
        try {
            // 上传文件路径
            String filePath = CoreConfig.getPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            Map<String, Object> map = new HashMap<>();
            map.put("fileName", fileName);
            map.put("url", url);
            return Result.ok(map);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 上传文件并存库
     * @param file
     * @return
     */
    @PostMapping("/common/upload/chatFile")
    @CrossOrigin("*")
    public Result uploadChatFile(MultipartFile file) {
        try {
            String md5Name =FileUtils.getFileMD5String(file);
            List<File> files = mongoTemplate.find(Query.query(Criteria.where("fileName").is(md5Name)), File.class);
            if(!files.isEmpty()){
                Map<String, Object> map = new HashMap<>();
                map.put("fileName", files.get(0).getFileName());
                map.put("url", files.get(0).getUrl());
                map.put("fileId", files.get(0).getId());
                return Result.ok(map);
            }

            String filePath = CoreConfig.getPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;

            File tempFile = new File();
            tempFile.setExt(fileName.substring(fileName.lastIndexOf(".") + 1));
            tempFile.setType("1");
            tempFile.setCreateDate(new Date());
            tempFile.setUrl(url);
            tempFile.setFileName(md5Name);
            mongoTemplate.insert(tempFile);

            Map<String, Object> map = new HashMap<>();
            map.put("fileName", md5Name);
            map.put("url", url);
            map.put("fileId", tempFile.getId());
            return Result.ok(map);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 删除文件并删除表
     * @param fileId
     */
    @DeleteMapping("/common/upload/chatFile/{fileId}")
    @CrossOrigin("*")
    public void removeChatFile(@PathVariable(value = "fileId") String fileId) {
        File file = mongoTemplate.findById(fileId, File.class);
        if (file == null || StringUtils.isEmpty(file.getFileName())) throw new RuntimeException("系统异常");
        String filePath = CoreConfig.getPath();
        String path = filePath + file.getFileName().substring(7);
        java.io.File tempFile = new java.io.File(path.replaceAll("\\/", "\\\\"));
        if (tempFile.exists()) {
            try {
                boolean delete = tempFile.delete();
                if (delete) {
                    mongoTemplate.findAndRemove(Query.query(Criteria.where("id").is(file.getId())), File.class);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/common/download/resource")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            if (!FileUtils.checkAllowDownload(resource)) {
                throw new Exception(StringUtils.format("资源文件({})非法，不允许下载。 ", resource));
            }
            // 本地资源路径
            String localPath = CoreConfig.getPath();
            // 数据库资源地址
            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }



}
